package com.yy.device.api;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.yy.device.api.web.APIModel;
import com.yy.device.api.web.APIModelHandler;
import com.yy.device.boot.DeviceDataContainer;
import com.yy.device.boot.DeviceServer;
import com.yy.device.boot.protocol.TaskMessage;
import com.yy.device.core.entity.Task;
import com.yy.device.core.service.TaskService;
import com.yy.device.enums.DeviceDataEnum;
import com.yy.device.enums.DeviceExeTaskStatus;
import com.yy.device.enums.DeviceFunctionEnum;
import com.yy.device.enums.SolenoidOutTypeEnum;
import com.yy.util.Assert;
import com.yy.util.Snowflake;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;


/**
 * BCR 扫码状态上报
 *
 * @author sunzhiqiang
 * @date 2021/12/09 15:16:05
 */
@Slf4j
@Component
public class TaskApi {

    @Resource
    private DeviceServer deviceServer;
    @Resource
    private TaskService taskService;

    /**
     * 基础开关任务指令
     *
     * @param request 任务实体类
     * @return {@link Long}
     */
    public APIModel command(Integer deviceCode, TaskMessage request) {
        return APIModelHandler.execute(model -> {
            long taskId = Snowflake.nextId();
            log.info("execute request:{}", JSON.toJSONString(request));
            Assert.isTrue(!Objects.isNull(request), "参数不允许是null");
            Assert.isTrue(!Objects.isNull(deviceCode), "设备编码不允许是null");
            Assert.isTrue(!Objects.isNull(request.getDeviceDataEnum()), "开关状态不允许是null");
            Assert.isTrue(!Objects.isNull(request.getDeviceFunctionEnum()), "功能码不允许是null");
            Assert.isTrue(request.getDevicePointCode() >= 0 && request.getDevicePointCode() < 8, "寄存器编号只能在0-7之间");
            Map<Integer, List<Short>> deviceDataMap = DeviceDataContainer.DEVICE_DATA_MAP;
            List<Short> list = deviceDataMap.get(deviceCode);
            if (CollectionUtils.isEmpty(list)) {
                model.setData(-1L);
                return;
            }
            list.remove(request.getDevicePointCode());
            list.add(request.getDevicePointCode(), request.getDeviceDataEnum().getType());
            Task task = new Task();
            task.setTaskId(taskId);
            task.setDeviceCode(deviceCode);
            task.setDevicePointCode((int) request.getDevicePointCode());
            task.setFunctionCommand(request.getDeviceFunctionEnum().getType());
            task.setDataCommand((int) request.getDeviceDataEnum().getType());
            task.setExeStatus(DeviceExeTaskStatus.NEW.name());
            Date date = new Date();
            task.setCreateTime(date);
            task.setUpdateTime(date);
            taskService.save(task);
            deviceServer.send(deviceCode, request);
            model.setData(request.getTaskId());
            log.info("execute request:{}.task:{}", JSON.toJSONString(request), JSON.toJSONString(task));
        });
    }


    /**
     * 硝化液回流电磁阀开关
     *
     * @param deviceCode     设备编号
     * @param deviceDataEnum 设备数据枚举
     * @return {@link APIModel}
     */
    public APIModel controDigestiveFluid(Integer deviceCode, DeviceDataEnum deviceDataEnum) {
        TaskMessage taskMessage = TaskMessage.createSend(DeviceFunctionEnum.OPEN,
                deviceDataEnum,
                SolenoidOutTypeEnum.DIGESTIVE_FLUID.getType()
        );
        return command(deviceCode, taskMessage);
    }

    /**
     * 污泥回流电磁阀开关
     *
     * @param deviceCode     设备编号
     * @param deviceDataEnum 设备数据枚举
     * @param taskId         任务id
     * @return {@link APIModel}
     */
    public APIModel controSludgeReturn(Integer deviceCode, DeviceDataEnum deviceDataEnum) {
        TaskMessage taskMessage = TaskMessage.createSend(DeviceFunctionEnum.OPEN,
                deviceDataEnum,
                SolenoidOutTypeEnum.SLUDGE_RETURN.getType()
        );
        return command(deviceCode, taskMessage);
    }

    /**
     * 曝气装置电磁阀开关
     *
     * @param deviceCode     设备编号
     * @param deviceDataEnum 设备数据枚举
     * @param taskId         任务id
     * @return {@link APIModel}
     */
    public APIModel controAeration(Integer deviceCode, DeviceDataEnum deviceDataEnum) {
        TaskMessage taskMessage = TaskMessage.createSend(DeviceFunctionEnum.OPEN,
                deviceDataEnum,
                SolenoidOutTypeEnum.AERATION.getType()
        );
        return command(deviceCode, taskMessage);
    }

    /**
     * 剩余污泥排放电磁阀开关
     *
     * @param deviceCode     设备编号
     * @param deviceDataEnum 设备数据枚举
     * @param taskId         任务id
     * @return {@link APIModel}
     */
    public APIModel controSludgeDischarge(Integer deviceCode, DeviceDataEnum deviceDataEnum) {
        TaskMessage taskMessage = TaskMessage.createSend(DeviceFunctionEnum.OPEN,
                deviceDataEnum,
                SolenoidOutTypeEnum.SLUDGE_DISCHARGE.getType()
        );
        return command(deviceCode, taskMessage);
    }

    /**
     * 剩余污泥排放电磁阀开关
     *
     * @param deviceCode 设备编号
     * @return {@link APIModel}
     */
    public APIModel stopAll(Integer deviceCode) {
        List<Long> list = Lists.newArrayListWithExpectedSize(SolenoidOutTypeEnum.values().length);
        for (SolenoidOutTypeEnum value : SolenoidOutTypeEnum.values()) {
            TaskMessage taskMessage = TaskMessage.createSend(DeviceFunctionEnum.OPEN,
                    DeviceDataEnum.CLOSED,
                    value.getType()
            );

            APIModel command = command(deviceCode, taskMessage);
            list.add((Long) command.getData());
        }
        return APIModelHandler.execute(model -> {
            model.setData(list);
        });
    }


}
